package com.muyan.sys.webscoket.service;

import com.muyan.sys.common.core.redis.RedisCache;
import com.muyan.sys.webscoket.constant.ChatCacheConstants;
import com.muyan.sys.webscoket.util.ChannelManager;
import io.netty.channel.ChannelHandlerContext;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class HeartbeatService {


    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ChannelManager channelManager;

    private static final int HEARTBEAT_TIMEOUT = 60; // 心跳超时时间（秒）




    /**
     * 更新用户心跳信息
     */
    public void updateHeartbeat(String userId, ChannelHandlerContext ctx) {
        String key = ChatCacheConstants.HEARTBEAT_KEY_PREFIX + userId;
        redisCache.setCacheObject(key, ctx.channel().remoteAddress().toString(), HEARTBEAT_TIMEOUT, TimeUnit.SECONDS);
    }

    /**
     * 删除用户心跳信息
     */
    public void removeHeartbeat(String userId) {
        String key = ChatCacheConstants.HEARTBEAT_KEY_PREFIX + userId;

        redisCache.deleteObject(key);
    }

    /**
     * 检查用户心跳是否超时
     */
    public boolean isHeartbeatTimeout(String userId) {
        String key = ChatCacheConstants.HEARTBEAT_KEY_PREFIX + userId;
        return redisCache.hasKey(key);

    }

    /**
     * 定期检查所有用户的心跳状态
     * 每30秒执行一次
     */
    @Scheduled(fixedRate = 30000)
    public void checkHeartbeats() {
        Set<String> keys = redisCache.keys(ChatCacheConstants.HEARTBEAT_KEY_PREFIX + "*");

        if (keys != null) {
            for (String key : keys) {
                String userId = key.substring(ChatCacheConstants.HEARTBEAT_KEY_PREFIX.length());
                if (isHeartbeatTimeout(userId)) {
                    // 心跳超时，关闭连接
                    closeConnection(userId);
                }
            }
        }
    }

    /**
     * 关闭超时连接
     */
    private void closeConnection(String userId) {
        channelManager.closeChannel(userId);
        removeHeartbeat(userId);
    }
} 